import { body, ValidationChain } from 'express-validator';

/**
 * 标签验证规则
 * 用于创建标签时的数据校验
 */
export const validateTag: ValidationChain[] = [
  body('name')
    .notEmpty()
    .withMessage('标签名称不能为空')
    .isLength({ min: 1, max: 50 })
    .withMessage('标签名称长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z0-9\s_-]+$/)
    .withMessage('标签名称只能包含中文、英文、数字、空格、下划线和连字符')
    .trim(),

  body('description')
    .optional()
    .isLength({ max: 200 })
    .withMessage('标签描述不能超过200个字符')
    .trim(),

  body('color')
    .optional()
    .matches(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
    .withMessage('颜色必须是有效的十六进制颜色值（如 #FF0000 或 #F00）'),

  body('icon')
    .optional()
    .isLength({ max: 50 })
    .withMessage('图标名称不能超过50个字符')
    .trim(),

  body('isActive')
    .optional()
    .isBoolean()
    .withMessage('激活状态必须是布尔值'),

  body('sortOrder')
    .optional()
    .isInt({ min: 0 })
    .withMessage('排序值必须是非负整数')
];

/**
 * 标签更新验证规则
 * 用于更新标签时的数据校验（所有字段都是可选的）
 */
export const validateTagUpdate: ValidationChain[] = [
  body('name')
    .optional()
    .notEmpty()
    .withMessage('标签名称不能为空')
    .isLength({ min: 1, max: 50 })
    .withMessage('标签名称长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z0-9\s_-]+$/)
    .withMessage('标签名称只能包含中文、英文、数字、空格、下划线和连字符')
    .trim(),

  body('description')
    .optional()
    .isLength({ max: 200 })
    .withMessage('标签描述不能超过200个字符')
    .trim(),

  body('color')
    .optional()
    .matches(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
    .withMessage('颜色必须是有效的十六进制颜色值（如 #FF0000 或 #F00）'),

  body('icon')
    .optional()
    .isLength({ max: 50 })
    .withMessage('图标名称不能超过50个字符')
    .trim(),

  body('isActive')
    .optional()
    .isBoolean()
    .withMessage('激活状态必须是布尔值'),

  body('sortOrder')
    .optional()
    .isInt({ min: 0 })
    .withMessage('排序值必须是非负整数')
];

/**
 * 分类验证规则
 * 用于创建分类时的数据校验
 */
export const validateClassify: ValidationChain[] = [
  body('name')
    .notEmpty()
    .withMessage('分类名称不能为空')
    .isLength({ min: 1, max: 50 })
    .withMessage('分类名称长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z0-9\s_-]+$/)
    .withMessage('分类名称只能包含中文、英文、数字、空格、下划线和连字符')
    .trim(),

  body('description')
    .optional()
    .isLength({ max: 200 })
    .withMessage('分类描述不能超过200个字符')
    .trim(),

  body('color')
    .optional()
    .matches(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
    .withMessage('颜色必须是有效的十六进制颜色值（如 #FF0000 或 #F00）'),

  body('icon')
    .optional()
    .isLength({ max: 50 })
    .withMessage('图标名称不能超过50个字符')
    .trim(),

  body('parentId')
    .optional()
    .isUUID()
    .withMessage('父分类ID必须是有效的UUID格式'),

  body('isActive')
    .optional()
    .isBoolean()
    .withMessage('激活状态必须是布尔值'),

  body('sortOrder')
    .optional()
    .isInt({ min: 0 })
    .withMessage('排序值必须是非负整数')
];

/**
 * 分类更新验证规则
 * 用于更新分类时的数据校验（所有字段都是可选的）
 */
export const validateClassifyUpdate: ValidationChain[] = [
  body('name')
    .optional()
    .notEmpty()
    .withMessage('分类名称不能为空')
    .isLength({ min: 1, max: 50 })
    .withMessage('分类名称长度必须在1-50个字符之间')
    .matches(/^[\u4e00-\u9fa5a-zA-Z0-9\s_-]+$/)
    .withMessage('分类名称只能包含中文、英文、数字、空格、下划线和连字符')
    .trim(),

  body('description')
    .optional()
    .isLength({ max: 200 })
    .withMessage('分类描述不能超过200个字符')
    .trim(),

  body('color')
    .optional()
    .matches(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
    .withMessage('颜色必须是有效的十六进制颜色值（如 #FF0000 或 #F00）'),

  body('icon')
    .optional()
    .isLength({ max: 50 })
    .withMessage('图标名称不能超过50个字符')
    .trim(),

  body('parentId')
    .optional()
    .isUUID()
    .withMessage('父分类ID必须是有效的UUID格式'),

  body('isActive')
    .optional()
    .isBoolean()
    .withMessage('激活状态必须是布尔值'),

  body('sortOrder')
    .optional()
    .isInt({ min: 0 })
    .withMessage('排序值必须是非负整数')
];

/**
 * 批量删除验证规则
 * 用于批量删除操作的数据校验
 */
export const validateBatchDelete: ValidationChain[] = [
  body('ids')
    .isArray({ min: 1 })
    .withMessage('IDs必须是非空数组')
    .custom((ids: string[]) => {
      if (!Array.isArray(ids)) {
        throw new Error('IDs必须是数组');
      }
      
      if (ids.length === 0) {
        throw new Error('至少需要提供一个ID');
      }
      
      if (ids.length > 100) {
        throw new Error('一次最多只能删除100个项目');
      }
      
      // 检查每个ID是否为有效的UUID格式
      const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
      for (const id of ids) {
        if (typeof id !== 'string' || !uuidRegex.test(id)) {
          throw new Error(`无效的ID格式: ${id}`);
        }
      }
      
      // 检查是否有重复的ID
      const uniqueIds = new Set(ids);
      if (uniqueIds.size !== ids.length) {
        throw new Error('ID列表中不能有重复项');
      }
      
      return true;
    })
];

/**
 * 分页查询参数验证规则
 * 用于分页查询的参数校验
 */
export const validatePaginationQuery: ValidationChain[] = [
  body('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('页码必须是大于0的整数'),

  body('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('每页数量必须是1-100之间的整数'),

  body('search')
    .optional()
    .isLength({ max: 100 })
    .withMessage('搜索关键词不能超过100个字符')
    .trim(),

  body('sortBy')
    .optional()
    .isIn(['name', 'createdAt', 'updatedAt', 'sortOrder'])
    .withMessage('排序字段必须是: name, createdAt, updatedAt, sortOrder 之一'),

  body('sortOrder')
    .optional()
    .isIn(['asc', 'desc'])
    .withMessage('排序方向必须是: asc 或 desc')
];